#ifndef _VN_PHYSICS_MANAGER_H_
#define _VN_PHYSICS_MANAGER_H_

#include "Box2D\Box2D.h"
#include "..\Graphics\Sprite.h"
#include <functional>
#include <vector>

class PhysicsManager
{
public:
	static PhysicsManager& getSingleton();
	static void clean();

	b2World& getWorld();
	void syncSprites();
	void step();
	void setDebugDraw(b2Draw* p_debugDraw);
	void drawDebugData();

	void flush();
	void reset();

	void prepareBodyForDestruction(b2Body* p_body) { m_bodiesToDestroy.push_back(p_body); }
	void prepareJointForDestruction(b2Joint* p_joint) { m_jointsToDestroy.push_back(p_joint); }

	void createCollision(const std::string& p_filepath);

	void removeSpriteSync(vn::Sprite* p_sprite);
	void removeSpriteSync(b2Body* p_b2Body);
	void addSpriteSync(b2Body* p_b2Body, vn::Sprite* p_sprite);
	void addEvent(std::function<void()> p_func) { m_events.push_back(p_func); }		// use this to queue forces while collision occurs
	void setPause(bool p_value) { m_pause = p_value; }
	void clearEvents() { m_events.clear(); }

protected:
	PhysicsManager(void);
	virtual ~PhysicsManager(void);

	static PhysicsManager* m_instance;

	std::vector<b2Body*> m_bodiesToDestroy;
	std::vector<b2Joint*> m_jointsToDestroy;

	std::vector<std::pair<vn::Sprite*, b2Body*>> m_syncList;
	std::vector<std::function<void()>> m_events;
	bool m_pause;
	b2World* m_world;
	b2Draw* m_debugDraw;
	b2ContactListener* m_contactListener;
};

#endif // _VN_PHYSICS_MANAGER_H_
